Go to QuArK Web Site
Structure of the program
Updated 02 Mar 2001
Upper levels:
QuArK Information Base
4. The Source Code

 4.4. Structure of the program

 [ Prev - Up - Next ] 

 Index


 QObjects

Armin Rigo - 15 Feb 2001   [ Top ] 

The most central part of QuArK is its internal objects on which everything else is based. These objects are represented by all the classes that directly or indirectly inherit from QObject, defined in qobjects.pas. Here are the main rules about QObjects.

Although the class QObject has got a few fields, these fields should be regarded as used by QuArK's internal management only. All important data must be stored using a combination of the two main features of QObjects : their Specific/Args and their subobjects.

Specific/Args are similar to the ones of Quake entities : it is a list of pairs of strings. The first string, the Specific, is an arbirary name for a setting; the corresponding second string gives the value of this setting.

Objects also each have a list of subobjects. This lets objects be organized in a hierarchy.

The basic principles are that the Specific/Args and the subobjects contain all the information, and that this object hierarchy is central for all operations :

  • to load a file, we actually convert it into an object or a hierarchy of objects;
  • to save a file, we convert the objects back to the destination file format;
  • we can only display and work with objects, never directly with files.


 QFileObjects

Armin Rigo - 15 Feb 2001   [ Top ] 

QFileObject is an abstract class that inherits from QObject. The general rule is that classes that inherit from QFileObject can be saved to or loaded from disk files, whereas classes that inherit from QObject only are internal objects whose purpose is only to be used as subobjects of other objects.

For example, here is how a map file is internally organized. The ".map" file type itself is managed by a class called QMapFile that inherits from QFileObject, whereas inside the map, the hierarchy of polyhedrons, groups, entities, etc. is represented by a hierarchy of objects that inherit from QObject, because there is no point in saving these objects as single files. Graphically :

Map object
 +-- worldspawn
      +-- polyhedron
      +-- polyhedron 2
      +-- group
           +-- entity
           +-- etc

The links in this diagram mean "is a sub-object".


 Loading files

Armin Rigo - 23 Feb 2001   [ Top ] 

Here are comments that will help you in writing support for a new file type.

QuArK has got a complex file management structure, but you need not be aware of it as long as you use the "official" way of loading and saving files. Doing so will let QuArK handle things such as loading or saving directly inside a .pak file, and load-on-demand.

To support a new file type, a class inherits from QFileObject and overrides some key methods. The first one is TypeInfo, which should return the file extension. QuArK recognize files based on their extension only, and then invokes the correct class'  LoadFile  method. This method must process the file it receive in a parameter and turn *all* information it contains into Specific/Args and subobjects.

For example, the method  LoadFile  of QMapFile parses the map file and creates the whole hierarchy of groups, polyhedrons and entities.

Some file types are suitable for load-on-demand, which is implemented through subobjects whose class also has a  LoadFile  method. For example, when loading a .PAK file, it is of course not completely loaded into memory : the directory of the file is processed, and folders and subfolders are created accordingly. The files inside the folders are also created but this time through the method  LoadedItem , which may be called from a  LoadFile  method only. It creates a subobject which is marked as "not loaded yet"; this subobject's own  LoadFile  method will be called when necessary to actually load the (sub-)file.

In summary, the method  LoadFile  must :

  • load every information contained in the file and store it all as Specific/Args and subobjects, with one exception : calls to  LoadedItem , which does not immediately load the data;
  • don't do anything else (no direct disk access, no display, etc.), with one exception : calls to LoadSibling, to access files besides the one currently loading (typically, Quake 2's models and sprites refer to .pcx files for the model skin and sprite images).


 Saving files

Armin Rigo - 23 Feb 2001   [ Top ] 

Saving files is the exact inverse of loading them. The method  SaveFile  must turn the Specific/Args and the subobjects structure back into a file.

If the  LoadFile  method used LoadSibling,  SaveFile  calls Info.WriteSibling (see QkMdl.pas).


 Displaying files

Armin Rigo - 15 Feb 2001   [ Top ] 

Files are never displayed directly in QuArK : only internal objects can be. This means that the display code must only rely on the Specific/Args and eventually on the subobjects hierarchy to display the content of a file.

The general rule about display is that subobjects are visible in a tree hierarchy and the user can edit them freely (add subobjects, rename or delete some, move them around, and so on).

For simple objects (typically, the ones with no subobject), the display form gives users access to all parameters of the object. For example, an image object is displayed in a form whose bottom gives parameters such as the size and the color depth of the image.

Semi-complex objects, paradoxally, have simpler display forms : their information is stored as subobjects and the user can edit them without any particular form. For example, a sprite object is basically just a list of images, so that it is represented as an object with images as subobjects. Editing them for the user is quite easy : all he has to do is rename, move, add, delete images. A particular sprite form is needed only for the stuff that cannot be edited this way, e.g. how long each image is to stay in the sprite animation sequence.

Really-complex objects (e.g. maps or models) require more sophisticated display code, which only gives a preview of the object when users click on it in the QuArK Explorer and invokes a complex editor when needed.

Note that for the subobjects of an object to be displayed in tree views, you need to override the IsExplorerItem method. This method controls whether each subobject is displayed or not, or whether it is allowed to be dropped there by the user or not. In general it should be implemented as follows :

function xxx.IsExplorerItem(Q: QObject) : TIsExplorerItem;
begin
 Result:=ieResult[(Q is someclass) or (Q is someotherclass) or...];
end;


GNU General Public License by The QuArK (Quake Army Knife) Community - http://www.planetquake.com/quark

 [ Prev - Top - Next ]